home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / program / 386 / utility / speed_1.s < prev    next >
Text File  |  1985-11-19  |  15KB  |  314 lines

  1.  ; Program Name: SPEED_1.S
  2.  ; Version: 1.006        
  3.  
  4.  ; Assembly Instructions:
  5.  
  6.  ;     Assemble in "PC-relative" mode and save with a TTP extension. 
  7.  
  8.  ; Execution Instructions:
  9.  
  10.  ;     SPEED_1.TTP will not execute unless the custom traps in program
  11.  ; TRAPS.PRG and TRAP_9.PRG have previously been installed.  The custom
  12.  ; traps are installed when those programs are executed from the desktop
  13.  ; or from an AUTO folder on a boot disk.
  14.  
  15.  ; NOTE: The time required for a program to be loaded into memory depends
  16.  ;       on the assembly mode used to assemble the program.  This will be
  17.  ;       shown, using SPEEDTST.TTP, in chapter 5.
  18.  
  19.  ;       In addition, a program's load time depends on the drive from which
  20.  ;       the program is loaded, the method used to format the disk on which
  21.  ;       the program is located, the position of the program on the disk
  22.  ;       and, in this case, the position of the child process relative to the
  23.  ;       position of the parent process.
  24.  
  25.  ;       To eliminate the drive-variables when comparing the load and
  26.  ;       execution times of one program to that of another, the parent and
  27.  ;       the child should be isolated to an otherwise empty partition or
  28.  ;       floppy disk for each spawning instance.
  29.  
  30.  ;       For example, if there are two programs involved in the comparison,
  31.  ;       first copy the parent, which is SPEED_1 in this case, so that it is
  32.  ;       the only item in the hard disk partition or on the floppy.  Then,
  33.  ;       copy the first program to the same partition or floppy.  Execute
  34.  ;       the parent, SPEED_1 in this case, and obtain the results.
  35.  
  36.  ;       Remove the first program and copy the second.  Execute the parent
  37.  ;       and obtain the results for the second program.
  38.  
  39.  ;     Execute from the desktop.  Type the name of an executable file which
  40.  ; has a TOS or PRG extension on SPEED_1.TTP's input parameter line.  The
  41.  ; name of the program you type on the parameter line must be in the same
  42.  ; directory as is SPEED_1.TTP and the program must be one that terminates
  43.  ; with GEMDOS function $4C.
  44.  
  45.  ;     Upon termination, the spawned program must return the value that is in
  46.  ; memory location $4BA immediately after it has been loaded, hereafter called
  47.  ; the after-load time or after-load value.  Custom trap #3 (get_time) can be
  48.  ; used to obtain that value.  SPEED_1.TTP uses the value returned in D0 to
  49.  ; calculate the spawned program's load and execution times.
  50.  
  51.  ;     The spawned program must terminate with GEMDOS function $4C so that
  52.  ; the after-load value can be returned in D0 by that function.  The value
  53.  ; returned in D0 by GEMDOS function $4C is limited to a 16 bit value.
  54.  
  55.  ;     If the spawned program has any halt or wait instructions, such as wait
  56.  ; for a keypress, etc., those should be commented out, then the program
  57.  ; should be assembled especially for the speed test.  Otherwise the
  58.  ; execution time will include the time waiting for input.
  59.  
  60.  ;     If custom trap #8 is used to terminate the program, the trap will
  61.  ; execute a wait_for_keypress algorithm when the program is executed from
  62.  ; the desktop, but it will omit the wait algorithm when the program is
  63.  ; spawned by SPEED_1.TTP.  In addition, trap #8 will return the after-load
  64.  ; value to SPEED_1.TTP and terminate the spawned program with GEMDOS function
  65.  ; $4C.
  66.  
  67.  ;     Both trap #8 and SPEED_1.TTP require that the spawned program be
  68.  ; initialized with custom trap #6.  See the note in the data section, below.
  69.  
  70.  ; Primary Function:
  71.  
  72.  ;     Spawn a process.  Calculate the spawned program's load and execution
  73.  ; times.  Store these values in a disk file that is identified by the name
  74.  ; of the spawned process with a DAT suffix.
  75.  
  76.  ;     If the spawned process directs output to the screen, store that output
  77.  ; in the same disk file.  Note: only screen directed output processed by
  78.  ; GEMDOS function $9 will be directed to the file.  If BIOS function $3 is
  79.  ; used for screen output, that output will not be redirected to the file.
  80.  
  81.  ; Secondary Function:
  82.  
  83.  ;     Verify that trap #6 is resident and functions correctly.  SPEED_1
  84.  ; confirms that because it will not be able to spawn a process unless 
  85.  ; the trap #6 call has returned excess memory to the system.
  86.   
  87.  ; Description:
  88.  
  89.  ;     SPEED_1 is the first in a series of programs which progress in
  90.  ; algorithmic perfection until the program SPEEDTST is developed.  Using
  91.  ; this series of programs, I intend to help you experience selected stages
  92.  ; of a program development process.
  93.  
  94.  ;     The primary attribute of this development process is its dependence,
  95.  ; during the early stages of development, on familiar documented algorithms
  96.  ; that can easily be found in references for many programming languages.  
  97.  ; After a working model has been developed with these familiar algorithms,
  98.  ; attempts are made to introduce unfamiliar algorithms which may be faster
  99.  ; or consume less memory.
  100.  
  101. release_excess_memory:
  102.  lea        program_end, a0     ; Put "end of program" address in A0.
  103.  movea.l    4(a7), a1           ; Put "basepage" address in A1.
  104.  movea.l    a1, a4              ; Copy to A4 for command line access.
  105.  trap       #6                  ; Calculate program size and release memory.
  106.  
  107.  ; NOTE: A local stack is not declared in PRG_5AP.TOS.  Because of the long
  108.  ;       string that is printed by that program, this program will bomb when
  109.  ;       it spawns PRG_5AP.TOS, if a local stack is not declared here.
  110.  
  111.  lea        stack, a7           ; Point A7 to this program's stack.
  112.  
  113.  ; The next task to be accomplished is an initialization algorithm.  The
  114.  ; name of the program that is to be typed on SPEED_1.TTP's input parameter
  115.  ; line must be used in several ways.  First, its suffix must be changed to
  116.  ; DAT so that it can be passed as a NULL terminated string when GEMDOS $3C
  117.  ; is invoked to create the disk file.
  118.  
  119.  ; Then it must be passed as a NULL terminated string with the program's
  120.  ; original suffix when GEMDOS $4B is invoked to spawn the program.
  121.  
  122.  ; Finally, the program's name is used as part of SPEED_1.TTP's output
  123.  ; header.
  124.  
  125.  ; The command line processing algorithm creates the required NULL terminated
  126.  ; strings, storing them in locations declared in the data section of SPEED_1.
  127.  
  128. process_command_line_parameters:
  129.  lea        $80(a4), a4         ; Fetch address of parameters.
  130.  move.b     (a4)+, d0           ; Fetch parameter line character count.
  131.  lea        program_name, a3    ; Load program_name address in A3.
  132.  subq.b     #1, d0              ; Set up counter.
  133.  ext.w      d0                  ; Extend to match the size of the dbra
  134.                                 ; instruction.
  135.  
  136.  ; NOTE: The dbcc instruction operates on a word length value, therefore,
  137.  ;       the value in the register that is to be decremented by a dbcc
  138.  ;       instruction must be placed there with a word size instruction, such
  139.  ;       as move.w #10, D0; or with a longword size instruction, as long as
  140.  ;       the value in the longword is limited to word size validity, or with
  141.  ;       a byte size instruction, as long as the value in the register is
  142.  ;       sign extended to word size, as is done in the instruction above.
  143.       
  144. fetch_character:                
  145.  move.b     (a4)+, (a3)+        ; Store character.
  146.  dbra       d0, fetch_character ; Loop until d0 becomes negative.
  147.  move.b     #0, (a3)            ; Finish with a NULL.
  148.  
  149. create_file_name:               ; Create a file to accept standard output.
  150.  lea        filename, a4
  151.  lea        program_name, a3
  152. copy_name:
  153.  move.b     (a3)+, (a4)+
  154.  cmpi.b     #$2E, (a3)          ; Is next byte of program_name the period?
  155.  bne.s      copy_name           ; Continue looping until period is seen.
  156.  move.b     #$2E, (a4)+         ; Add a period.
  157.  move.b     #$44, (a4)+         ; Add letter 'D'.
  158.  move.b     #$41, (a4)+         ; Add letter 'A'.
  159.  move.b     #$54, (a4)+         ; Add letter 'T'.
  160.  move.b     #0, (a4)            ; Add a NULL.
  161.  
  162. create_file:
  163.  move.w     #0, -(sp)           ; File attribute = read/write.
  164.  pea        filename            ; Will be name of spawned process + .DAT.
  165.  move.w     #$3C, -(sp)         ; Function = f_create = GEMDOS $3C.
  166.  trap       #1                  ; File handle is returned in D0.
  167.  addq.l     #8, sp
  168.  lea        file_handle, a0     ; Store returned file handle.
  169.  move.w     d0, (a0)
  170.  
  171. redirect_output:                ; Exchange file handle with screen's handle.
  172.  move.w     file_handle, -(sp)  ; This is the disk file's handle.
  173.  move.w     #1, -(sp)           ; This is the video screen's handle.
  174.  move.w     #$46, -(sp)         ; Function = f_force = GEMDOS $46.
  175.  trap       #1
  176.  addq.l     #6, sp
  177.  
  178. get_start_time:
  179.  lea        start_time, a3      ; Fetch address of variable "start_time".
  180.  trap       #3                  ; Returns value of system clock in D0.
  181.  move.w     d0, (a3)            ; Save start time.
  182.  
  183. load_and_execute_program:
  184.  pea        environ_string
  185.  pea        command_line
  186.  pea        program_name
  187.  move.w     #0, -(sp)
  188.  move.w     #$4B, -(sp)         ; Function = GEMDOS $4B = p_exec.
  189.  trap       #1                 
  190.  move.w     d0, d3              ; Copy after-load value to D3 for calculation.
  191.  
  192. get_end_time:
  193.  trap       #3                  ; Returns value of system clock in D0.
  194.  move.w     d0, d5              ; Copy to D5 for calculation.
  195.  sub.w      d3, d5              ; Subtract after-load time from end time.
  196.  ext.l      d5                  ; Extend to 32 bits.
  197.  
  198.  ; NOTE: D5 now contains the spawned program's execution time, but the time
  199.  ;       has not yet been converted to milliseconds.  See the note below
  200.  ;       concerning the sign extension of D3 and D5.
  201.  
  202. reposition_stack_pointer:
  203.  lea        $10(sp), sp        
  204.  
  205.  ;       Note the difference between the use of GEMDOS function $19 below and
  206.  ;       the way it is used on page 116 of the Internals book.  In the 
  207.  ;       Internals book there are two errors: (1) sp should not be referenced
  208.  ;       indirectly, as (sp); (2) the ASCII code for the letter A should be
  209.  ;       added to the contents of the register--in the internals book the
  210.  ;       contents of the register are added to the ASCII code for the letter
  211.  ;       A.
  212.  
  213. get_drive:
  214.  move.w     #$19, -(sp)         ; Function = dgetdrv = GEMDOS $19.
  215.  trap       #1                  ; Returns 0 for drive A, 1 for B, etc.
  216.  addq.l     #2, sp              
  217.  add.b      #$41, d0            ; Add ASCII value for A to compute ASCII
  218.  lea        drive, a0           ; letter code for the drive value returned.
  219.  move.b     d0, (a0)            ; Save drive's ASCII letter code.
  220.  
  221. print_heading:
  222.  lea        heading, a0
  223.  bsr        print_string
  224.  lea        program_name, a0
  225.  bsr        print_string
  226. print_drive_for_spawned_program:
  227.  lea        drive_msg, a0
  228.  bsr        print_string
  229.  
  230. compute_load_time:
  231.  lea        load_time_msg, a0
  232.  bsr.s      print_string
  233.  lea        start_time, a3
  234.  sub.w      (a3), d3            ; Subtract start time from after-load time.
  235.  ext.l      d3                  ; Extent to 32 bits.
  236.  
  237.  ; SIGN EXTENSION NOTE
  238.  
  239.  ;    The value in D3, above, and in D5 previously, is extended to 32 bits
  240.  ; because, although the number of 200hz intervals we are able to utilize is
  241.  ; limited to a word size by the value that is returned in D0 via GEMDOS
  242.  ; function $4C, the time converted to milliseconds can extend beyond that
  243.  ; word size limitation.
  244.  
  245.  trap       #9                  ; See description in TRAP_9.S.
  246.  
  247. close_file:
  248.  move.w     file_handle, -(sp)
  249.  move.w     #$3E, -(sp)         ; Function = fclose = GEMDOS $3E.
  250.  trap       #1
  251.  addq.l     #4, sp
  252.  
  253. terminate:
  254.  move.w     #0, -(sp)
  255.  trap       #1
  256.  
  257. print_string:                   ; Expects address of string to be in A0.
  258.  pea        (a0)                ; Push address of string onto stack.
  259.  move.w     #9, -(sp)           ; Function = c_conws = GEMDOS $9.
  260.  trap       #1                  ; GEMDOS call
  261.  addq.l     #6, sp              ; Reset stack pointer to top of stack.
  262.  rts
  263.  
  264.  data
  265. heading:          dc.b $D,$A,"SPEED_1.TTP Execution Results",$D,$A
  266.                   dc.b       "for ",0
  267. drive_msg:        dc.b ", loaded from drive: "
  268. drive:            dc.b "A",$D,$A,0
  269. load_time_msg:    dc.b $D,$A,"  Load time:    ",0
  270.  
  271.  ; NOTE: Custom trap #6 checks the environmental string pointer of each
  272.  ;       program that invokes it to see if the pointer contains the address
  273.  ;       of the label "environ_string" below.  That test is performed by
  274.  ;       comparing the contents of the address contained in the pointer to
  275.  ;       the ASCII string "TERM" declared below.
  276.  
  277.  ;       When a match occurs, it means that the program invoking trap #6 has
  278.  ;       been spawned by SPEED_1 (or by a similar program), therefore, trap
  279.  ;       #6 sets the value of the boolean variable "spawned", declared by
  280.  ;       TRAPS.PRG, to all ones = true.
  281.  
  282.  ;       When custom trap #8 is invoked by a program, the state of the
  283.  ;       variable "spawned" is tested.  If the state is true, the program
  284.  ;       invoking custom trap #8 is terminated with GEMDOS function $4C and
  285.  ;       the after-load time, which was saved by custom trap #6, is returned
  286.  ;       to the parent program.
  287.  
  288.  ;       If the state of "spawned" is false, GEMDOS function $8 is executed
  289.  ;       so that execution will pause for a keypress.  When the keypress is
  290.  ;       received, GEMDOS function $0 is executed.
  291.  
  292.  ;       In this manner, custom trap #8, working in conjunction with custom
  293.  ;       trap #6, eliminates the "wait for keypress" algorithm automatically
  294.  ;       when a program is spawned by SPEED_1 (or a similar program).  This
  295.  ;       prevents the computed execution time from being corrupted by a time
  296.  ;       period that involves a wait for keyboard input.
  297.   
  298. environ_string:   dc.b "TERM",0
  299. command_line:     dc.b 0       
  300.  align
  301.  bss
  302. start_time:       ds.w    1     ; Value in $4BA just before spawning.
  303. file_handle:      ds.w    1     ; Handle for the filename below.
  304. filename:         ds.l    4     ; File name for execution results.
  305. program_name:     ds.l    4     ; Filename buffer.  Must be NULL terminated.
  306.                   ds.l   96     ; Program stack.
  307. stack:            ds.l    0     ; Address of program stack.
  308. program_end:      ds.l    0
  309.  end
  310.  
  311.  
  312.  
  313.  
  314.